package com.ctakit.kiwi.web.util;

import cn.hutool.core.util.StrUtil;
import org.springframework.web.servlet.support.RequestContext;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Map;

/**
 * @author andyhome 线程工具类
 */
public abstract class ThreadLocalUtils {
    private static final ThreadLocal<HttpServletRequest> request = new ThreadLocal<>();
    private static final ThreadLocal<RequestContext> requestContext = new ThreadLocal<>();
    private static final ThreadLocal<HttpServletResponse> response = new ThreadLocal<>();
    private static final ThreadLocal<String> uri = new ThreadLocal<>();
    private static final ThreadLocal<String> uriExt = new ThreadLocal<>();
    private static final ThreadLocal<String> token = new ThreadLocal<>();
    private static final ThreadLocal<Map<String, Object>> data = new ThreadLocal<>();


    public static void setToken(String value) {
        token.set(value);
    }

    public static String getToken() {
        return token.get();
    }

    public static void removeToken() {
        token.remove();
    }

    public static void setUriExt(String value) {
        uriExt.set(value);
    }

    public static String getUriExt() {
        return uriExt.get();
    }

    public static void removeUriExt() {
        uriExt.remove();
    }

    public static void setData(Map<String, Object> value) {
        data.set(value);
    }

    public static Map<String, Object> getData() {
        return data.get();
    }

    public static void removeData() {
        data.remove();
    }

    public static HttpServletRequest getRequest() {
        return request.get();
    }

    public static RequestContext getRequestContext() {
        RequestContext rqc = requestContext.get();
        if (rqc == null) {
            requestContext.set(new RequestContext(getRequest()));
        } else {
            return rqc;
        }
        return requestContext.get();
    }

    public static void setRequest(HttpServletRequest value) {
        request.set(value);
    }

    public static void removeRequest() {
        requestContext.remove();
        request.remove();
    }

    public static HttpServletResponse getResponse() {
        return response.get();
    }

    public static void setResponse(HttpServletResponse value) {
        response.set(value);
    }

    public static void removeResponse() {
        response.remove();
    }

    public static HttpSession getSession() {
        return getRequest().getSession(true);
    }


    public static String getUri() {
        return uri.get();
    }

    public static void setUri(String value) {
        ThreadLocalUtils.uri.set(value);
    }

    public static void removeUri() {
        uri.remove();
    }

    public static void removeAll() {
        ThreadLocalUtils.removeRequest();
        ThreadLocalUtils.removeResponse();
        ThreadLocalUtils.removeUri();
        ThreadLocalUtils.removeUriExt();
        ThreadLocalUtils.removeToken();
        ThreadLocalUtils.removeData();
    }

    public static void addAttribute(String name, Object value) {
        if (StrUtil.isNotBlank(name)) {
            if (value != null) {
                ThreadLocalUtils.getData().put(name, value);
                ThreadLocalUtils.getRequest().setAttribute(name, value);
            } else {
                ThreadLocalUtils.getData().remove(name);
                ThreadLocalUtils.getRequest().removeAttribute(name);
            }
        }
    }

    public static Object getRequestAttribute(String name) {
        return ThreadLocalUtils.getRequest().getAttribute(name);
    }

    public static String getRequestParameter(String name) {
        return ThreadLocalUtils.getRequest().getParameter(name);
    }

    public static String getCurrentMethodName() {
        // 获取堆栈跟踪
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();

        // 第0个元素是当前线程的getStackTrace方法，第1个元素是调用getCurrentMethodName方法的方法，第2个元素是当前方法
        if (stackTrace.length >= 3) {
            return stackTrace[2].getMethodName();
        } else {
            return "Unknown Method";
        }
    }
}
